import { ref, reactive, Ref } from 'vue';
import Caption from 'src/models/Caption';
import { defineStore } from 'pinia';
export interface CaptionStateInterface {
  /***
   * the goal is only operate captionList array then sync to the current video caption
   */
  captionList: Caption[];
  currentVideo: HTMLVideoElement | null;
  currentTrack: TextTrack | null;
  activeCueId: string | null;
}
export const useCaptionStroe = defineStore('caption', {
  state: (): CaptionStateInterface => ({
    captionList: reactive([]),
    currentVideo: null,
    currentTrack: null,
    activeCueId: null,
  }),
  getters: {
    captionsByTime(): Caption[] {
      const newArr = Array.from(this.captionList);
      return newArr.sort((a, b) => a.startTime - b.startTime);
    },
  },
  actions: {
    newCaption(videoEl: HTMLVideoElement, name = 'editing') {
      this.currentVideo = videoEl;
      this.currentTrack = this.currentVideo.addTextTrack('captions', name);
      this.currentTrack.mode = 'showing';
      this.captionList = [];
      this.currentTrack.addEventListener('cuechange', () => {
        if (this.currentTrack?.activeCues?.length) {
          this.activeCueId = this.currentTrack.activeCues[0].id;
        } else {
          this.activeCueId = null;
        }
      });
    },
    async loadCaptionFromUrl(url: string) {
      const res = await fetch(url);
      const data = await res.text();
      console.log(data);
    },
    /***
     * import a caption file from local
     */
    importCaption() {},
    restoreCaption() {},
    saveCaption() {},
    /***
     * remove a text track from current video
     */
    deleteTextTrack() {},
    addCaption(
      start: number,
      duration: number,
      text: string,
      id?: string
    ): VTTCue | null {
      if (this.currentTrack) {
        const caption = new Caption(
          start,
          duration,
          text,
          id ? id : this.captionList.length.toString()
        );
        const cue = new VTTCue(
          caption.startTime,
          caption.endTime,
          caption.text
        );
        cue.id = caption.id;
        caption.cue = cue;
        this.captionList!.push(caption);
        this.currentTrack.addCue(cue);
        return cue;
      } else {
        return null;
      }
    },
    addCaptionByCaption(
      target: Caption,
      type: 'top' | 'bottom'
    ): VTTCue | null {
      if (this.currentTrack) {
        const startTime = type === 'top' ? target.startTime : target.endTime;
        const caption = new Caption(
          startTime,
          target.duration,
          target.text,
          this.captionList.length.toString()
        );
        const cue = new VTTCue(
          caption.startTime,
          caption.endTime,
          caption.text
        );
        cue.id = caption.id;
        caption.cue = cue;
        this.captionList!.push(caption);
        this.currentTrack.addCue(cue);
        return cue;
      } else {
        return null;
      }
    },
    combineCaption(caption1: Caption, caption2: Caption) {
      caption1.endTime = caption2.endTime;
      caption1.text = caption1.text + '\n' + caption2.text;
      caption1.cue!.endTime = caption2.endTime;
      caption1.cue!.text = caption1.text;
      this.currentTrack!.removeCue(caption2.cue!);
      this.captionList = this.captionList.filter(
        (caption) => caption.id !== caption2.id
      );
    },
    getCueById(id: string): VTTCue | null {
      if (this.currentTrack) {
        return this.currentTrack.cues!.getCueById(id) as VTTCue;
      } else {
        return null;
      }
    },
    removeCaptionById(id: string) {
      if (this.currentTrack) {
        this.currentTrack.removeCue(this.getCueById(id)!);
        this.captionList = this.captionList.filter((caption) => {
          return caption.id !== id;
        });
      }
    },
    removeCaption(caption: Caption) {
      if (this.currentTrack) {
        this.currentTrack.removeCue(caption.cue!);
        this.captionList = this.captionList.filter(
          (item) => item.id !== caption.id
        );
      }
    },
    splitCaption(caption: Caption, time: number) {
      const cue = caption.cue;
      if (cue) {
        const newCue = this.addCaption(time, caption.endTime - time, cue.text);
        if (newCue) {
          cue.endTime = time;
          caption.endTime = time;
        }
      }
    },
    updateText(caption: Caption, text: string) {
      if (caption) {
        caption.text = text;
        if (caption.cue) {
          caption.cue.text = text;
        }
      }
    },
    updateStartTime(caption: Caption, time: number) {
      if (caption) {
        caption.startTime = time;
        if (caption.cue) {
          caption.cue.startTime = time;
          caption.cue.endTime = time + caption.duration;
        }
      }
    },
    updateEndTime(caption: Caption, time: number) {
      if (caption) {
        caption.endTime = time;
        caption.duration = caption.endTime - caption.startTime;
        if (caption.cue) {
          caption.cue.endTime = time;
        }
      }
    },
    updateDuration(caption: Caption, duration: number) {
      if (caption) {
        caption.duration = duration;
        if (caption.cue) {
          caption.cue.endTime = caption.endTime;
        }
      }
    },
    updateCaption(caption: Caption) {
      const cue = this.getCueById(caption.id);
      if (cue) {
        cue.startTime = caption.startTime;
        cue.endTime = caption.endTime;
        cue.text = caption.text;
      }
      const oldCaption = this.captionList.find(
        (item) => item.id === caption.id
      );
      if (oldCaption) {
        oldCaption.startTime = caption.startTime;
        oldCaption.endTime = caption.endTime;
        oldCaption.text = caption.text;
      }
    },
    exportCaption() {},
    downloadCaption() {},
    pad2(number: number) {
      return (number < 10 ? '0' : '') + number;
    },

    pad3(number: number) {
      return number >= 100 ? number : '0' + this.pad2(number);
    },
    formatTime(time: number) {
      let hours = 0;
      let minutes = 0;
      let seconds = 0;
      let milliseconds = 0;
      while (time >= 60 * 60) {
        hours++;
        time -= 60 * 60;
      }
      while (time >= 60) {
        minutes++;
        time -= 60;
      }
      while (time >= 1) {
        seconds++;
        time -= 1;
      }
      milliseconds = parseInt((time * 1000).toFixed(0));
      return (
        this.pad2(hours) +
        ':' +
        this.pad2(minutes) +
        ':' +
        this.pad2(seconds) +
        '.' +
        this.pad3(milliseconds)
      );
    },
  },
});
